#include "bitmap.h"

/* bitmap for lowest bit 1 (byte=0 is illegal import) */
const mx_uint8_t bitmap_lowest[256] = {
    0, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
    4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
    5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
    4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
    6, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
    4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
    5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
    4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
    7, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
    4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
    5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
    4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
    6, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
    4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
    5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
    4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0
};

/* bitmap for highest bit 1 (byte=0 is illegal import) */
const mx_uint8_t bitmap_highest[256] = {
    0, 0, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3,
    4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
    5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
    5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
    6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
    6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
    6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
    6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
    7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
    7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
    7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
    7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
    7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
    7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
    7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
    7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7
};

/**
 * get the lowest bit 1 in mx_uint16_t
 * @param dat: target data
 * @return: bit index
 */
mx_uint8_t bitmap_lsbidx16 (mx_uint16_t dat)
{
    mx_uint8_t ret;
    if ((mx_uint8_t)dat != 0)
        ret = bitmap_lsbidx8((mx_uint8_t)dat);
    else
        ret = bitmap_lsbidx8((mx_uint8_t)(dat >> 8)) + 8;
    return ret;
}

/**
 * get the lowest bit 1 in mx_uint32_t
 * @param dat: target data
 * @return: bit index
 */
mx_uint8_t bitmap_lsbidx32 (mx_uint32_t dat)
{
    mx_uint8_t ret;
    if ((mx_uint16_t)dat != 0)
        ret = bitmap_lsbidx16((mx_uint16_t)dat);
    else
        ret = bitmap_lsbidx16((mx_uint16_t)(dat >> 16)) + 16;
    return ret;
}

/**
 * get the lowest bit 1 in mx_uint64_t
 * @param dat: target data
 * @return: bit index
 */
mx_uint8_t bitmap_lsbidx64 (mx_uint64_t dat)
{
    mx_uint8_t ret;
    if ((mx_uint32_t)dat != 0)
        ret = bitmap_lsbidx32((mx_uint32_t)dat);
    else
        ret = bitmap_lsbidx32((mx_uint32_t)(dat >> 32)) + 32;
    return ret;
}

/**
 * get the highest bit 1 in mx_uint16_t
 * @param dat: target data
 * @return: bit index
 */
mx_uint8_t bitmap_msbidx16 (mx_uint16_t dat)
{
    mx_uint8_t ret;
    mx_uint8_t tmp;
    if ((tmp = (mx_uint8_t)(dat >> 8)) != 0)
        ret = bitmap_msbidx8(tmp) + 8;
    else
        ret = bitmap_msbidx8((mx_uint8_t)(dat));
    return ret;
}

/**
 * get the highest bit 1 in mx_uint32_t
 * @param dat: target data
 * @return: bit index
 */
mx_uint8_t bitmap_msbidx32 (mx_uint32_t dat)
{
    mx_uint8_t ret;
    mx_uint16_t tmp;
    if ((tmp = (mx_uint16_t)(dat >> 16)) != 0)
        ret = bitmap_msbidx16(tmp) + 16;
    else
        ret = bitmap_msbidx16((mx_uint16_t)(dat));
    return ret;
}

/**
 * get the highest bit 1 in mx_uint64_t
 * @param dat: target data
 * @return: bit index
 */
mx_uint8_t bitmap_msbidx64 (mx_uint64_t dat)
{
    mx_uint8_t ret;
    mx_uint32_t tmp;
    if ((tmp = (mx_uint32_t)(dat >> 32)) != 0)
        ret = bitmap_msbidx32(tmp) + 32;
    else
        ret = bitmap_msbidx32((mx_uint32_t)(dat));
    return ret;
}
